#pragma once

#include "thread.h"

#ifdef _DEBUG
	#import "..\\..\\..\\Target\\Debug\\ButtonWPForm.tlb"
#else
	#import "..\\..\\..\\Target\\Release\\ButtonWPForm.tlb"
#endif
using namespace ButtonWPForm;

namespace Ooganizer
{

	enum BUTTON_STATE
	{
		// These are the states that coincide with the states defined
		// in ButtonWPFormCCW
		BUTTON_NONE = 0, 
		BUTTON_DOWN = 1,    // BUTTON_ADD				
		BUTTON_TOGGLED = 2, // BUTTON_DELETE

		// Button Up is the Hover image (Used on Mouse Over),
		// it is NOT DEFINED in ButtonWPFormCCW
		BUTTON_UP = 1000
	};

	////
	// ButtonThemeSetting, this static holds our current Button Theme Setting
	// ~This structure can be reloaded when a ThemeChange occured (WM_THEMECHANGED)
	////
	struct ButtonThemeSetting
	{
		// Init Flags
		bool bIsInitialized;
		bool bIsChanged;

		// Int Button Dimension/Location
		long Top;
		long Right;
		long Height;
		long Width;

		// String Button Locations
		_bstr_t bstrBUTTON_UP;
		_bstr_t bstrBUTTON_DOWN;
		_bstr_t bstrTOGGLE_UP;
	
		ButtonThemeSetting()
		{
			Top = 0;
			Right = 0;
			Height = 0;
			Width = 0;
			bIsInitialized = false;
			bIsChanged = false;
		}
	};

	class CWHPaccess;	
	class WPFCaller;

	#define BLANK_HookWndItem(n) HookWndItem n = {NULL,NULL,NULL,NULL}
	//////////////////////////////////////////////////////////////////////
	// Strc: HookWndItem
	// Desc: Hook Item is used in the HookedWndList. Each HookWndItem keeps track
	//		 of all the addresses needed for each hook for each Windows, 
	//		 as well as each Window's WPFCaller.		
	//////////////////////////////////////////////////////////////////////
	struct HookWndItem
	{	
		HWND hWnd;	
		WNDPROC HookWndProc;
		WNDPROC DefWndProc;		
		WPFCaller* wpfcaller;
	};	
	//////////////////////////////////////////////////////////////////////
	// Clss: WPFCaller
	// Desc: This class is responsible for overriding wndproc draw routines
	//       and communicate to the WPF COM object 
	//////////////////////////////////////////////////////////////////////
	class WPFCaller : Thread
	{
	public:		
		// All Windows Messages *Except NCDestroy & UnHook* enter here
		virtual LRESULT OnDefault (HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
		WPFCaller(HookWndItem Item, HINSTANCE hInstance);
		~WPFCaller();

		// Each WPFCaller is mapped to a HookWndItem		
		HWND m_hWnd;
		WNDPROC m_HookWndProc;
		WNDPROC m_DefWndProc;								 
		HINSTANCE m_hInst;

		// Window W32 State Settings
		int m_wndHeight;
		int m_wndWidth;
		RECT m_wndRECT;

		// We need to keep track of the Button State in order 
		// to know what to draw
		BUTTON_STATE m_ButtonState;
		BUTTON_STATE m_ButtonToggledState; // We can overwrite buttonDown state
										   // with another state. this allows us to 
										   // specify which state to use to overwrite.

		BUTTON_STATE m_ButtonStateLastSaved;
		BUTTON_STATE m_ButtonToggledStateLastSaved;
		bool m_bButtonIsArtificiallyHidden;
		bool m_bButtonIsMinimized;
		bool m_bButtonIsBeingRestored;

		// Transparency / Fade Effect
		BYTE GetAlpha();
		void SetAlpha(BYTE bAlpha);
		void StartRestoreEventFadeTimer();

		// WPFProc Will load the Button Settings via COM which
		// we'll use to draw the Icon
		ButtonThemeSetting m_ButtonThemeSetting;

		// COM Objects
		IButtonFormPtr m_wpfForm;
		
		// ~This class has two handles (one to the COM WPF Form)
		//  (another to the w32 button)
		HWND  m_hwndWPForm;
		HWND  m_hwndW32Window;
			
		// ThreadStuff		
		bool m_bThreadIsReady;
		HANDLE m_thread;
		DWORD m_threadID;

	private:
		// Win32 Button Window * Created for better speed *
		// Responsible for setting up the WNDCLASSEX struct and register the Window
		BOOL InitApplication(HINSTANCE hInstance);		
		// Responsible for Creating and Showing a new Window Class Instance
		BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
		// Thread Entry
		int WINAPI threadproc(HINSTANCE hinstance, HINSTANCE hPrevInstance, void* vArg, int nCmdShow);
		// Thread Entry
		virtual DWORD Run(LPVOID vArg)
		{
			return(threadproc(m_hInst,NULL,vArg,TRUE));
		}
	};
}